<?php
/*
    Dispatcher takes the URL information, parses it for paramters and
    tells the involved controllers what to do.
*/

class Dispatcher extends Object {
    var $cache_url = '';
    var $cache = false;

    //Dispatches and invokes given URL, handing over control to the involved controllers, and then renders the results (if autoRender is set). 
    function dispatch() {
        $this->url = $this->get_url();
        $params = $this->parse_params($this->url);

        switch($params['controller']) {
            case 'template_loader':
                $this->template_redirect($params);
                return null;
                break;
            case 'rss2':
                $this->rss2();
                return null;
                break;
        }

        $controller = $this->__get_controller($params['controller']);
        if (!empty($params['data']))
            $controller->data =& $params['data'];
        else
            $controller->data = null;
        $controller->referer = $params['url'];
        $controller->action =& $params['action'];

        $controller->auth_redirect();
        $controller->_init_components();
        $controller->construct_classes();
        return $this->_invoke($controller, $params);
    }

    // Invokes given controller's render action if autoRender option is set. Otherwise the contents of the operation are returned as a string.
    function _invoke(&$controller, $params) {
        call_user_func_array(array(&$controller, $params['action']), $params['params']);
        if ($controller->autoRender) {
            $output = $controller->render();
        }
        return null;
    }

    // Get controller to use
    function __get_controller($controller_name) {
        $controller = null;
        $plugin_dir = apply_filters('plugin_dir', $controller_name);
        if ($plugin_dir == $controller_name) {
            $app = ARLICLE . 'app/';
        } else {
            $app = ROOT . 'www/plugins/' . $plugin_dir . '/app/';
            define('PLUGIN_DIR', $plugin_dir);
            define('PLUGIN', ROOT . 'www/plugins/' . $plugin_dir);
        }

        $controller_file = $app . 'controller/' . $controller_name . '_controller.php';
        if (!file_exists($controller_file)) {
            error_404();
        }

        require LIBS . 'controller/controller.php';
        require $controller_file;
        $controller_class = str_replace(" ", "", ucwords(str_replace("_", " ", $controller_name))) . 'Controller';
        if (class_exists($controller_class))
        $controller =& new $controller_class();
        $controller->file_name = $controller_name;
        return $controller;
    }

    // Returns array of GET and POST parameters. GET parameters are taken from given URL.
    function parse_params($url) {
        $params = Router::parse($url);
        $params['form'] = $_POST;
        if (isset($params['form']['data'])) {
            $params['data'] = $params['form']['data'];
            unset($params['form']['data']);
        }
        if(!empty($_GET)) {
            $return_url = array_keys($_GET);
            $params['url'] = $return_url[0];
            if (strpos($params['url'], '/index_php/') !== false) {
                $params['url'] = str_replace('/index_php/', '/index.php/', $params['url']);
            }
            unset($return_url);
        } else {
            $params['url'] = null;
        }
        foreach ($_FILES as $name => $data) {
            if ($name != 'data') {
                $params['form'][$name] = $data;
            }
        }

        if (isset($_FILES['data'])) {
            foreach ($_FILES['data'] as $key => $data) {
                foreach ($data as $model => $fields) {
                    foreach ($fields as $field => $value) {
                        $params['data'][$model][$field][$key] = $value;
                    }
                }
            }
        }
        return $params;
    }

    // Returns the REQUEST_URI from the server environment
    function get_url() {
        $uri = strstr(env('REQUEST_URI'),'?') ? substr(env('REQUEST_URI'), 0, strpos(env('REQUEST_URI'), '?')) : env('REQUEST_URI');
        $url = null;
        if (get_option('url_model') != 'htaccess') {
            $url = 'index.php';
        }
        $uri = str_replace('index.php', '', $uri);
        $base = str_replace('index.php', '', env('SCRIPT_NAME'));
        Router::set_base($base);

        if (!empty($url)) {
            Router::set_url($base . $url);
        } else {
            Router::set_url(rtrim($base, '/'));
        }
        $uri = substr($uri, strlen($base));
        $uri = trim($uri,'/');
        return $uri;
    }

    function template_redirect($params) {
        if (!empty($this->url)) {
            $this_url = "/$this->url/";
        } else {
            $this_url = '';
        }

        # if user is admin, no cache
        $current_user = current_user();
        if (CACHE && empty($current_user->id)) {
            if ($this->cache($params)) {
                return null;
            }
        } else {
            $this->cache = false;
        }
        $GLOBALS['params'] = $params['params'];

        define('TEMPLATE', get_option('template'));
        define('TEMPLATE_DIR', ROOT . 'www/themes/' . TEMPLATE . '/');
        define('THEMES_URL', Router::get_base() . 'www/themes/' . TEMPLATE . '/');

        require LIBS . 'views/helper.php';
        require LIBS . 'views/helpers/html.php';
        $html = new HtmlHelper();
        $GLOBALS['html'] = $html;
        require_once LIBS . 'template/template_loader.php';

        $urls = array();
        $no_cache = array();
        $no_compress = array();
        $custom_files[] = 'ini';
        $custom_files[] = 'functions';
        $custom_files[] = 'urls';
        $custom_files[] = 'settings';
        foreach($custom_files as $custom_file) {
            $file = TEMPLATE_DIR . 'libs/' . $custom_file . '.php';
            if (file_exists($file)) {
                require $file;
            }
        }
        # get the urls as a serialize string
        $tmp_urls_path = TMP_PATH . 'themes/urls.php';
        $tmp_urls_string = '';
        $tmp_urls = array();
        if (file_exists($tmp_urls_path)) {
            $tmp_urls_string = file_get_contents($tmp_urls_path);
            $tmp_urls = unserialize($tmp_urls_string);
            if (empty($tmp_urls)) {
                $tmp_urls = array();
            }
        }

        # the dynamic add have the priority
        $urls = $tmp_urls + $urls;

        unset($file);
        unset($custom_file);
        unset($custom_files);
        unset($action_file);
        ob_start();

        $url = $this_url;
        if (empty($url)) {
            $url = '/';
        }

        if (isset($urls) && !empty($urls[$url])) {
            define('THIS_URL', $this_url);
            $template_file = TEMPLATE_DIR . $urls[$url] . '.php';
        } else if (isset($urls) && !empty($urls)) {
            # set the part of the url
            $keys = array_keys($urls);
            $count = count($keys);

            for($count; $count > 0; $count--) {
                $key = array_pop($keys);
                if (strpos($key, '/^\/') === 0) {
                    // for regular expression

                    $a = preg_match($key, $url);
                    if ($a > 0) {
                        define('THIS_URL', $this_url);

                        parse_template_params($url, $key);
                        $template_file =  TEMPLATE_DIR . $urls[$key] . '.php';
                        break;
                    }
                } else {
                    if (empty($key)) {
                        continue;
                    }
                    $pos = strpos($url, $key);
                    if ($pos !== false && $key != '/') {
                        // set the url without parameter as the this url
                        define('THIS_URL', $key);
                        parse_template_params($url, $key);
                        $template_file =  TEMPLATE_DIR . $urls[$key] . '.php';
                        break;
                    }
                }
            }
        }
        if (!empty($template_file)) {
            if (is_readable($template_file)) {
                require_once($template_file);
            } else {
                arlicle_die(__('Template file is not exists'));
            }
        } else {
            error_404(false);
        }
        $contents = ob_get_contents();
        ob_end_clean();
        if (defined('ERROR_404')) {
            error_404();
        }
        # replace the themes (image, css, swf, js, ) url
        # css
        $contents = preg_replace('/(<link\shref=["|\'])(?:\.\/|\.\.\/)?(css\/)?([a-z0-9A-Z_]+\.css["|\']\srel=["|\']stylesheet["|\']\stype=["|\']text\/css["|\'])/i','\1' . THEMES_URL . '\2\3', $contents);
        # js
        $contents = preg_replace('/(<script\s(?:type|language)=["|\']text\/javascript["|\']\ssrc=["|\'])(?:\.\/|\.\.\/)?(js\/[a-z0-9A-Z_\-\.]+\.(?:js|vbs)["|\']><\/script>)/', '\1' . THEMES_URL . '\2', $contents);
        # image
        $contents = preg_replace('/((?:background|src)\s*=\s*["|\'])(?:\.\/|\.\.\/)?(images\/.*?["|\'])/is', '\1' . THEMES_URL . '\2', $contents);
        $contents = preg_replace('/((?:background|background-image):\s*?url\()(?:\.\/|\.\.\/)?(images\/)/is', '\1' . THEMES_URL . '\2', $contents);

        if (empty($no_cache[$url]) && $this->cache && !empty($contents)) {
            # compress the html data
            if(empty($no_compress[$url])) {
                require LIBS . 'compactor.php';
                $compactor = new Compactor(array(
                    'buffer_echo' => false
                ));
                $contents = $compactor->squeeze($contents);
            }
            $this->cache_object->setexpirytime(CACHE_TIMEOUT);
            $this->cache_object->storedata($contents,1);
        }
        echo $contents;
        return null;
    }

    function cache($params) {
        $this->cache = true;
        if (Router::is_admin()) {
            $this->cache_url = CACHE_PATH . ARLICLE_ADMIN . '/' . implode('_', $params['params']);
        } else {
            if (!empty($params['params'][0])) {
                $file_name = implode('_', $params['params']);
            } else {
                $file_name = $params['template'];
            }
            $this->cache_url = CACHE_PATH . $file_name;
        }
        $this->cache_object = new CacheClass();
        $this->cache_object->path = $this->cache_url;
        $success=$this->cache_object->updating($updating);
        if ($success) {
            $success=$this->cache_object->verifycache($updated);
            $this->cache_object->error;
            $this->cache_object->path;
            if ($success) {
                if ($updated) {
                    $endofcache=0;
                    for(;!$endofcache;) {
                        $success=$this->cache_object->retrievefromcache($data,$endofcache);
                        if (!($success)) {
                            break;
                        }
                        echo $data;
                    }
                    return true;
                }
            }
        }
        return false;
    }

    function rss2() {
        require_once LIBS . 'template/template_loader.php';
        require_once LIBS . 'rss2.php';
    }
}
?>
